<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>树形表格 - layui</title>
    <link rel="stylesheet" href="./assets/dist/css/layui.css" />
  </head>
  <body class="layui-padding-5">
    <table class="layui-hide" id="test"></table>

    <script type="text/html" id="TPL-treeTable-demo">
      <div class="layui-btn-container">
        <button class="layui-btn layui-btn-sm" lay-event="getChecked">
          获取选中数据
        </button>
      </div>
    </script>

    <script type="text/html" id="TPL-treeTable-demo-tools">
      <div class="layui-btn-container">
        <a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="detail"
          >查看</a
        >
        <a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="addChild"
          >新增</a
        >
        <a class="layui-btn layui-btn-xs" lay-event="more"
          >更多 <i class="layui-icon layui-icon-down"></i
        ></a>
      </div>
    </script>

    <script src="./assets/dist/layui.js"></script>
    <script>
      // IE8 support
      // ES5 15.4.4.19 Array.prototype.map ( callbackfn [ , thisArg ] )
      // From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/Map
      if (!Array.prototype.map) {
        Array.prototype.map = function (fun /*, thisp */) {
          if (this === void 0 || this === null) {
            throw TypeError();
          }

          var t = Object(this);
          var len = t.length >>> 0;
          if (typeof fun !== 'function') {
            throw TypeError();
          }

          var res = [];
          res.length = len;
          var thisp = arguments[1],
            i;
          for (i = 0; i < len; i++) {
            if (i in t) {
              res[i] = fun.call(thisp, t[i], i, t);
            }
          }

          return res;
        };
      }

      // ES5 15.4.4.20 Array.prototype.filter ( callbackfn [ , thisArg ] )
      // From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/Filter
      if (!Array.prototype.filter) {
        Array.prototype.filter = function (fun /*, thisp */) {
          if (this === void 0 || this === null) {
            throw TypeError();
          }

          var t = Object(this);
          var len = t.length >>> 0;
          if (typeof fun !== 'function') {
            throw TypeError();
          }

          var res = [];
          var thisp = arguments[1],
            i;
          for (i = 0; i < len; i++) {
            if (i in t) {
              var val = t[i]; // in case fun mutates this
              if (fun.call(thisp, val, i, t)) {
                res.push(val);
              }
            }
          }

          return res;
        };
      }
      layui.use(['treeTable', 'dropdown', 'layer'], () => {
        var treeTable = layui.treeTable;
        var dropdown = layui.dropdown;
        var layer = layui.layer;

        // 渲染
        var inst = treeTable.render({
          elem: '#test',
          url: './assets/json/treeTable/demo-1.json',
          // data: createData(!0),
          maxHeight: 'full-32',
          toolbar: '#TPL-treeTable-demo',
          tree: {
            customName: {
              name: 'name',
            },
            view: {
              iconLeaf: '',
            },
            data: {
              // isSimpleData: true
            },
          },
          cols: [
            [
              { type: 'checkbox', fixed: 'left' },
              { type: 'numbers', fixed: 'left' },
              {
                field: 'id',
                title: 'ID',
                width: 145,
                sort: true,
                fixed: 'left',
                totalRow: '合计：',
              },
              { field: 'name', title: '用户名', width: 180, fixed: 'left' },
              { field: 'experience', title: '积分', width: 90, sort: true },
              { field: 'sex', title: '性别', width: 80, sort: true },
              { field: 'score', title: '评分', width: 80, sort: true },
              { field: 'city', title: '城市', width: 150 },
              { field: 'description', title: '描述', minWidth: 200 },
              { field: 'createTime', title: '创建时间', width: 170 },
              {
                fixed: 'right',
                title: '操作',
                width: 190,
                align: 'center',
                toolbar: '#TPL-treeTable-demo-tools',
              },
            ],
          ],
          page: true,
        });

        // 单元格工具事件
        treeTable.on('row(test)', (obj) => {
          console.log(obj);
        });

        // 表头工具栏工具事件
        treeTable.on('toolbar(' + inst.config.id + ')', (obj) => {
          var config = obj.config;
          var tableId = config.id;
          var status = treeTable.checkStatus(tableId);
          // 获取选中行
          if (obj.event === 'getChecked') {
            if (!status.data.length) return layer.msg('无选中数据');
            console.log(status);
            layer.alert(
              '当前数据选中已经输出到控制台，<br>您可按 F12 从控制台中查看结果。',
            );
          }
        });

        // 单元格工具事件
        treeTable.on('tool(' + inst.config.id + ')', function (obj) {
          var layEvent = obj.event; // 获得 lay-event 对应的值
          var trElem = obj.tr;
          var trData = obj.data;
          var tableId = obj.config.id;
          if (layEvent === 'detail') {
            layer.msg('查看操作：' + trData.name);
          } else if (layEvent === 'addChild') {
            var data = { id: Date.now(), name: '新节点' };
            var newNode2 = treeTable.addNodes(tableId, {
              parentIndex: trData['LAY_DATA_INDEX'],
              index: -1,
              data: data,
            });
          } else if (layEvent === 'more') {
            // 下拉菜单
            dropdown.render({
              elem: this, // 触发事件的 DOM 对象
              show: true, // 外部事件触发即显示
              align: 'right', // 右对齐弹出
              data: [
                {
                  title: '修改积分',
                  id: 'edit',
                },
                {
                  title: '删除',
                  id: 'del',
                },
              ],
              click: (menudata) => {
                if (menudata.id === 'del') {
                  console.log(trData);
                  layer.confirm('真的删除行么', (index) => {
                    obj.del(); // 等效如下
                    // treeTable.removeNode(tableId, trElem.attr('data-index'))
                    layer.close(index);
                  });
                } else if (menudata.id === 'edit') {
                  layer.prompt(
                    {
                      value: trData.experience,
                      title: '输入新的积分',
                    },
                    (value, index) => {
                      obj.update({ experience: value }); // 等效如下
                      // treeTable.updateNode(tableId, trElem.attr('data-index'), {experience: value});
                      layer.close(index);
                    },
                  );
                }
              },
            });
          }
        });
      });
    </script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/Mock.js/1.0.0/mock-min.js"></script>
    <script>
      // 生成模拟数据
      const createData = (flat) => {
        // 生成随机 ID 函数
        const createId = (() => {
          let nextId = 1;
          return () => nextId++;
        })();
        // 生成节点函数
        const createNode = (parentId = null, level = 0) => {
          const id = createId();
          const children =
            level < 3
              ? Mock.mock({
                  'array|0-5': [createNode.bind(null, id, level + 1)],
                }).array
              : [];
          const isParent = 'isParent';
          return {
            id,
            name: `User-${id}`,
            type: Mock.mock('@d6'),
            status: Mock.Random.d4(),
            score: Mock.Random.d100(),
            experience: Mock.Random.integer(1000, 99999),
            sex: Mock.Random.cword('男女', 1),
            city: Mock.Random.city(),
            description: '-',
            createTime: Mock.mock('@datetime'),
            [flat || 'parentId']: parentId,
            [flat || 'children']: children,
            [flat || isParent]: !!children.length,
          };
        };

        // 根节点
        const rootNodes = Mock.mock({
          'array|10-20': [createNode],
        }).array;

        if (flat) return rootNodes;

        // 生成树
        const getTreeData = (nodes) => {
          const result = [];
          nodes.forEach((node) => {
            result.push({
              ...node,
              parentId: null,
              children: getTreeData(node.children),
            });
          });
          return result;
        };
        return getTreeData(rootNodes);
      };
    </script>
  </body>
</html>
